package model;

import java.util.Observable;

/**
 * Stores the state of the program, controls the specific information 
 * displayed in the role frame.
 * @author Sarah George
 * @version Autumn 2012
 */
public class State extends Observable {
	
	/**
	 * Field to hold the FileParser.
	 */
	private FileParser parser;
	
	/**
	 * Field to hold the name of the currently logged in user.
	 */
	private String my_name;
	
	/**
	 * Field to hold the current conference.
	 */
	private Conference my_conf;
	
	/**
	 * Field to hold the current user.
	 */
	private User my_user; //user object
	
	/**
	 * Field to hold the current role.
	 */
	private Role my_role;
	
	/**
	 * Field to hold the list of conferences a user is associated with.
	 */
	private Conference[] conf_list;
	
	/**
	 * Field to hold list of roles avaliable to the user for the chosen conference.
	 */
	private Role[] role_list;
	
	/**
	 * Field to tell if the user is valid.
	 */
	private boolean is_user_valid;
	
	/**
	 * Field to tell if the conference is valid.
	 */
	private boolean is_conf_valid;
	
	/**
	 * Field to tell if the role is valid.
	 */
	private boolean is_role_valid;
	
	/**
	 * Field to tell if the state is valid.
	 */
	private boolean is_state_valid;
	
	/**
	 * Field to denote that login is allowed.
	 */
	public static final int ALLOW_LOGIN = 999;
	
	/**
	 * Field to denote that login is not allowed.
	 */
	public static final int DISALLOW_LOGIN = 888;
	
	/**
	 * Constructor for a state class.
	 * @param the_parser the file parser for the data
	 */
	public State(FileParser the_parser) {
		parser = the_parser;
		conf_list = new Conference[5]; 
		//5 chosen for testing purposes and to be bigger that our data
		role_list = new Role[4]; //4=number of possible roles
		initLists();
		is_user_valid = false;
		is_conf_valid = false;
		is_role_valid = false;
		is_state_valid = false;
	}
	
	/**
	 * Method to initialize the lists of conferences and roles.
	 */
	public void initLists() {
		int length = conf_list.length;
		for (int i = 0; i < length; i++) {
			conf_list[i] = new Conference();
		}
		int l = role_list.length;
		for (int i = 0; i < l; i++) {
			role_list[i] = Role.AUTHOR; //base case is that user is an author
		}
	}
	
	/**
	 * Temporary Empty Constructor for a state class. 
	 * To be used with first tests;
	 * before a file parser actually exists.
	 */
	public State() {
	}
	
	
	/**
	 * Method to determine if the data provided is valid;
	 * Will return true only if the file parser says that
	 * the file provided it is valid.
	 * @return valid a boolean value
	 */
	public boolean validData() {
		return parser.isValidData();
	}
	
	/**
	 * Method to get the file parser.
	 * @return parser the file parser.
	 */
	public FileParser getParser() {
		return parser;
	}
	
	/**
	 * Method to set the name connected with the 
	 * current state.
	 * @param the_name
	 */
	public void setName(String the_name) {
		my_name = the_name;
	}

	/**
	 * method to fetch the name associated with the 
	 * currently "logged in" user.
	 * @return my_name the String name associated with the 
	 * current user.
	 */
	public String getName() {
		return my_name;
	}
	
	/**
	 * Method to set the user.
	 * @param the_user the current user.
	 */
	public void setUser(User the_user) {
		my_user = the_user;
	}
	
	/**
	 * Method to return the current user.
	 * @return my_user the current user
	 */
	public User getUser() {
		return my_user;
	}
	
	/**
	 * Method to validate a user.
	 */
	public void validateUser() {
		my_user = parser.getUserWithUserName(my_name.toLowerCase());
		
		is_user_valid = (my_user != null);
		setUserConfs(my_user); //still set the user conference (to blank if need be)
		
	}
	
	/**
	 * Method to get list of conferences for a user.
	 * Calls NotifyObservers at end.
	 * @param the_user the current user.
	 */
	public void setUserConfs(User the_user) {
		
		if (the_user == null)
		{
			setChanged();
			conf_list = new Conference[0]; //pass an empty array if bad user
		} else {
			int user_id = my_user.getID();
			conf_list = parser.getConferencesForUser(user_id);
		}
		setChanged();
		notifyObservers(conf_list);
	}
	
	/**
	 * Method to set the current conference.
	 * @param the_conference the current conference.
	 */
	public void setConference(Conference the_conference) {
		
		is_conf_valid = (the_conference != null);
		if (is_conf_valid)
			my_conf = the_conference;
		
		setRoleList();
	}
	
	/**
	 * Method to return the current conference.
	 * @return my_conf the current conference
	 */
	public Conference getConference() {
		return my_conf;
	}
	
	/**
	 * Method to set the role.
	 * @param the_role the given role
	 */
	public void setRole(Role the_role) {
		my_role = the_role;
		is_role_valid = true;
		my_user.setRole(the_role);
	}
	
	/**
	 * Method to get the list of roles for a user and conference combination.
	 * Calls Notify Observers when complete.
	 */
	public void setRoleList() {
		if(is_conf_valid)
		{
			int uID = my_user.getID();
			int cID = my_conf.getConfID();
			role_list = parser.getRolesForUser(uID, cID);
		} else {
			role_list = new Role[0]; //pass empty role list.
		}
		
		setChanged();
		notifyObservers(role_list);
	}

	/**
	 * Method to return the current role.
	 * @return my_role the curren role
	 */
	public Role getRole() {
		return my_role;
	}

	/**
	 * Method to set the current state.
	 * @param the_name the user's name
	 * @param the_conf the current conference
	 * @param the_role the current role
	 */
	public void setState(String the_name, Conference the_conf, Role the_role) {
		setName(the_name);
		setConference(the_conf);
		setRole(the_role);
	}


	/**
	 * Method  to see if login is valid.
	 * @return is_state_valid only true if state is valid.
	 */
	public boolean loginValid() {
		if (is_user_valid && is_conf_valid && is_role_valid) {
			is_state_valid = true;
		}
		is_state_valid = true;//test
		return is_state_valid;
	}
	
	/**
	 * Method to allow login.
	 * @param allow boolean that determines if login occurs.
	 */
	public void allowLogin(boolean allow)
	{
		setChanged();
		if (allow)
			notifyObservers(ALLOW_LOGIN);
		else
			notifyObservers(DISALLOW_LOGIN);
			
	}	
	
} //End class State